#include "ComponentMoveAwayBehavior.h"
#include "Components/ComponentCreature.h"
#include "Components/ComponentBody.h"
#include "Components/ComponentHealth.h"
#include "Components/ComponentCreatureSounds.h"
#include "Components/ComponentCreatureSounds.h"
#include "ComponentPathfinding.h"
#include "Subsystems/SubsystemTerrain.h"
#include "Subsystems/SubsystemTimeOfDay.h"
#include "Subsystems/SubsystemBodies.h"

#include "GameRandom.hpp"
#include "Engine/MathUtils.hpp"
#include "GameSingleton.h"
#include "Log.h"
#include "GameRegistry.hpp"
#include "GameSingleton.h"
#include "GameThreadPool.hpp"

#include "Managers/BlocksManager.h"
#include "Blocks/WaterBlock.h"

#include <iostream>
#include <cfloat>

namespace PocketSurvival
{

    // ************** 【状态机】 **************

    ComponentMoveAwayBehavior::StateMachine::StateMachine(ComponentMoveAwayBehavior *moveAwayBehavior) : m_moveAway(moveAwayBehavior), EasyMachine(MachineState::Inactive) 
    {
        enter();
    }

    void ComponentMoveAwayBehavior::StateMachine::enter()
    {
        switch (m_currentState)
        {
        case MachineState::Inactive:
            MACHINE_DELEGATE()
            {
                m_moveAway->m_importanceLevel = 0.0f;
                m_moveAway->m_targetEntity = entt::null;
            }
            break;
        case MachineState::Move:
            MACHINE_DELEGATE()
            {
                if (GameSingleton::gameRandom->getFloat(0.0f, 1.0f) < 0.5f)
                {
                    // m_moveAway->componentCreature->componentCreatureSounds->playIdleSound(true);
                }
                if (m_moveAway->m_targetEntity != entt::null)
                {
                    if (GameSingleton::gameRegistry->valid(m_moveAway->m_targetEntity))
                    {
                        ComponentBody *targetBody = GameSingleton::gameRegistry->get<ComponentBody *>(m_moveAway->m_targetEntity);
                        Vector3 targetPosition;
                        Vector3 targetVelocity;
                        targetBody->getPosition(targetPosition);
                        targetBody->getVelocity(targetVelocity);
                        
                        Vector3 vector = targetPosition + 0.5f * targetVelocity;

                        Vector3 position;
                        m_moveAway->componentCreature->componentBody->getPosition(position);


                        Vector2 v = Vector2::Normalize(Vector2(position.posX - vector.posX, position.posZ - vector.posZ));
                        Vector2 vector2 = FastVector2::Zero;
                        float num = FLT_MIN;

                        float tarValue = (float)MathUtils::GetPI() * 2.0f;
                        for (float num2 = 0.0f; num2 < tarValue; num2 += 0.1f)
                        {
                            Vector2 vector3 = Vector2::CreateFromAngle(num2);
                            if (Vector2::Dot(vector3, v) > 0.2f)
                            {
                                Vector3 forward = m_moveAway->componentCreature->componentBody->getMatrix().getForward();
                                float num3 = Vector2::Dot(Vector2(forward.posX, forward.posZ), vector3);
                                if (num3 > num)
                                {
                                    vector2 = vector3;
                                    num = num3;
                                }
                            }
                        }
                        float s = GameSingleton::gameRandom->getFloat(1.5f, 2.0f);
                        float speed = m_moveAway->m_isFast ? 0.7f : 0.35f;
                        m_moveAway->componentPathfinding->setDestination(position + s * Vector3(vector2.posX, 0.0f, vector2.posY), speed, 1.0f, 0, false ,true, false, nullptr);
                    }
                    else
                    {
                        m_moveAway->m_targetEntity = entt::null;
                    }
                }
            }
            break;
        }
    }

    void ComponentMoveAwayBehavior::StateMachine::update(float dt)
    {
        switch (m_currentState)
        {
        case MachineState::Inactive:
            MACHINE_DELEGATE()
            {
                if (m_moveAway->isActive())
                {
                    changeTo(MachineState::Move);
                }
                if (m_moveAway->m_targetEntity != entt::null)
                {
                    m_moveAway->m_importanceLevel = 6.0f;
                }
            }
            break;
        case MachineState::Move:
            MACHINE_DELEGATE()
            {

            }
            break;
        }
    }

    void ComponentMoveAwayBehavior::StateMachine::leave() {}

    // **************************************



    ComponentMoveAwayBehavior::~ComponentMoveAwayBehavior()
    {
        delete m_stateMachine;
    }

    float ComponentMoveAwayBehavior::getImportanceLevel()
    {
        return m_importanceLevel;
    }

    void ComponentMoveAwayBehavior::update(float dt)
    {
        m_stateMachine->update(dt);
    }



    static const std::string componentName = "MoveAwayBehavior";
    const std::string &ComponentMoveAwayBehavior::getName() const
    {
        return componentName;
    }
    const std::string &ComponentMoveAwayBehavior::GetName()
    {
        return componentName;
    }
    void ComponentMoveAwayBehavior::load(const nlohmann::json &jsonData)
    {
        componentCreature = GameSingleton::gameRegistry->get<ComponentCreature *>(entity);
        componentPathfinding = GameSingleton::gameRegistry->get<ComponentPathfinding *>(entity);

        m_stateMachine = new StateMachine(this);
    }

}
